﻿@page "/boxplot"
@using VectSharp;
@using VectSharp.SVG;
@using VectSharp.Plots
@using MathNet.Numerics.Distributions;

<style>
    table {
        table-layout: fixed;
    }

    td {
        width: 200px;
        padding: 10px;
    }
</style>



<div style="width: 100vw; height: 100vh; position: relative;">
    <div style="height: 100vh; position: absolute; top: 0; left: 50%; transform: translateX(-50%)">
        <table style="width: 100vw">
            <tr>
                <td colspan="2" style="text-align: center">
                    <img src="@imgSource" style="max-height: calc(100vh - 250px)" />
                </td>
            </tr>
            <tr style="height: 250px">
                <td>
                    <table style="width: 100vw">
                        <tr>
                            <td>
                                <MatSelect Label="Whiskers" @bind-Value="@whiskers">
                                    <MatOption TValue="int" Value="0">Full range</MatOption>
                                    <MatOption TValue="int" Value="1">IQR · 1.5</MatOption>
                                    <MatOption TValue="int" Value="2">Standard deviation</MatOption>
                                </MatSelect>
                            </td>
                            <td>
                                <MatCheckbox Label="Show outliers" @bind-Value="@outliers"></MatCheckbox>
                            </td>
                        </tr>
                        <tr>
                            <td>
                                <MatCheckbox Label="Use notches" @bind-Value="@notches"></MatCheckbox>
                            </td>

                            <td>
                                <MatSelect Label="Orientation" @bind-Value="@orientation">
                                    <MatOption TValue="int" Value="0">Vertical</MatOption>
                                    <MatOption TValue="int" Value="1">Horizontal</MatOption>
                                </MatSelect>
                            </td>
                        </tr>
                        <tr>
                            <td>
                                <MatCheckbox Label="Proportional width" @bind-Value="@propWidth"></MatCheckbox>
                            </td>
                            <td>
                                <MatNumericUpDownField Label="Spacing"
                                                       @bind-Value=@spacing
                                                       Step="0.1" Minimum="0" Maximum="1" DecimalPlaces="2">
                                </MatNumericUpDownField>
                            </td>
                        </tr>
                    </table>
                </td>
            </tr>
        </table>
    </div>
</div>

@code {
    private double _spacing = 0.1;
    private double spacing
    {
        get
        {
            return _spacing;
        }
        set
        {
            _spacing = value;
            Render();
        }
    }

    private int _whiskers = 1;
    private int whiskers
    {
        get
        {
            return _whiskers;
        }
        set
        {
            _whiskers = value;
            Render();
        }
    }

    private bool _notches = false;
    private bool notches
    {
        get
        {
            return _notches;
        }
        set
        {
            _notches = value;
            Render();
        }
    }

    private bool _propWidth = true;
    private bool propWidth
    {
        get
        {
            return _propWidth;
        }
        set
        {
            _propWidth = value;
            Render();
        }
    }

    private bool _outliers = true;
    private bool outliers
    {
        get
        {
            return _outliers;
        }
        set
        {
            _outliers = value;
            Render();
        }
    }

    private int _orientation = 0;
    private int orientation
    {
        get
        {
            return _orientation;
        }
        set
        {
            _orientation = value;
            Render();
        }
    }

    private string imgSource = "";

    protected override Task OnInitializedAsync()
    {
        Render();
        return Task.CompletedTask;
    }

    static (string, IReadOnlyList<double>)[] data = new (string, IReadOnlyList<double>)[]{
    ( "N(0, 1)", Normal.Samples(0, 1).Take(500).ToArray() ),
    ( "N(2, 1)", Normal.Samples(2, 1).Take(1000).ToArray() ),
    ( "Γ(3, 3)", Gamma.Samples(3, 3).Take(100).ToArray() ),
    ( "E(1)", Exponential.Samples(1).Take(200).ToArray() ),
    ( "LogNorm(1, 0.2)", LogNormal.Samples(1, 0.2).Take(300).ToArray()) };

    public void Render()
    {
        Plot.WhiskerType whiskerType = Plot.WhiskerType.IQR_1_5;

        switch (whiskers)
        {
            case 0:
                whiskerType = Plot.WhiskerType.FullRange;
                break;
            case 1:
                whiskerType = Plot.WhiskerType.IQR_1_5;
                break;
            case 2:
                whiskerType = Plot.WhiskerType.StandardDeviation;
                break;
        }

        Plot plot = Plot.Create.BoxPlot(data, useNotches: notches, proportionalWidth: propWidth,
        xAxisTitle: orientation == 0 ? "Distributions" : null, title: "Box plot", yAxisTitle: orientation == 1 ? "Distributions" : null, vertical: orientation == 0, spacing: spacing, showOutliers: outliers, whiskerType: whiskerType);

        Page pag = plot.Render();

        Page page = pag;

        using (MemoryStream ms = new MemoryStream())
        {
            page.SaveAsSVG(ms);
            ms.Seek(0, SeekOrigin.Begin);

            using (StreamReader sr = new StreamReader(ms))
            {
                this.imgSource = "data:image/svg+xml;base64," + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(sr.ReadToEnd()));
            }
        }
    }
}
